package com.group.itms.routes.map;

import java.util.ArrayList;
import java.util.List;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.View;
import android.view.ViewGroup.LayoutParams;

public class Layer {

	private int mId;
	private Projection mProjection;
	private Type mType;
	private boolean mVisible = true;
	private boolean mRedrawMap = true;
	private String name;

	private Paint mRoutePaint = new Paint();
	
	public Layer() {
		mRoutePaint.setStyle(Style.STROKE);
		mRoutePaint.setStrokeWidth(8);
		mRoutePaint.setColor(Color.BLUE);
	}
	
	protected List<Marker> mMarkers = new ArrayList<Marker>();

	private OfflineMap mMap;

	public int getId() {
		return mId;
	}

	public void setId(int id) {
		this.mId = id;
	}

	public void setRedrawMap(boolean redrawMap) {
		mRedrawMap = redrawMap;
	}
	
	public Projection getProjection() {
		return mProjection;
	}

	public void setProjection(Projection projection) {
		this.mProjection = projection;
	}

	public Type getType() {
		return mType;
	}

	public void setType(Type type) {
		this.mType = type;
	}

	public boolean isVisible() {
		return mVisible;
	}

	public void setVisible(boolean visible) {
		mVisible = visible;
		redrawMap();
	}

	public List<Marker> getMarkers() {
		return mMarkers;
	}

	public Marker getNearestMarkerToScreenPoint(float x, float y) {
		if (mType == Type.ROUTE) {
			return null;
		}
		float dist, minDist = Float.MAX_VALUE;
		Marker nM = null;
		for (Marker m : mMarkers) {
			PointD scLoc = m.getScreenLocation(mProjection);
			dist = (float) Math.hypot(x - scLoc.x, y - scLoc.y);
			if (dist < minDist) {
				minDist = dist;
				nM = m;
			}
		}
		return nM;
	}

	public OfflineMap getMap() {
		return mMap;
	}

	public void setMap(OfflineMap mMap) {
		this.mMap = mMap;
	}

	public void addMarkers(List<Marker> markers) {
		mRedrawMap = false;
		for (Marker m : markers) {
			addMarker(m);
		}
		mRedrawMap = true;
		redrawMap();
	}

	public void addMarker(Marker marker) {
		mMarkers.add(marker);
		marker.setLayer(this);
		redrawMap();
	}

	public void clearMarkers() {
		mMarkers.clear();
		redrawMap();
	}

	void redrawMap() {
		if (mRedrawMap && mMap != null) {
			mMap.redrawView();
		}
	}

	public OfflineMapView getMapView() {
		if (mMap != null) {
			return mMap.getMapView();
		}
		return null;
	}

	public void draw(Canvas canvas) {
		if (mType == Type.ROUTE) {
			drawRoute(canvas);
		} else {
			drawDots(canvas);
		}
	}

	private void drawRoute(Canvas canvas) {
		int n = mMarkers.size();
		float[] pts = new float[n * 4];
		for (int i = 0, j = 0; j < n - 1; i += 4,j++) {
			PointD loc1 = mMarkers.get(j).getScreenLocation(mProjection);
			PointD loc2 = mMarkers.get(j + 1).getScreenLocation(mProjection);
			pts[i] = (float)loc1.x;
			pts[i + 1] = (float)loc1.y;
			pts[i + 2] = (float)loc2.x;
			pts[i + 3]  = (float)loc2.y;
		}
		canvas.drawLines(pts, mRoutePaint);
	}
	
	private void drawDots(Canvas canvas) {
		for (Marker m : mMarkers) {
			PointD loc = m.getScreenLocation(mProjection);
			if (m.getClickCount() == 1) {
				drawInfoView(canvas, m.getInfoView(), (int) (loc.x), (int) (loc.y));
			}
			Bitmap iconBmp = m.getIcon();
			canvas.drawBitmap(iconBmp, (float)loc.x, (float)loc.y, null);
		}
	}

	private void drawInfoView(Canvas canvas, View infoView, int l, int t) {
		if (infoView == null) {
			return;
		}
		infoView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		int h = infoView.getMeasuredHeight();
		int w = infoView.getMeasuredWidth();
		infoView.layout(l, t, l + w, t + h);
		canvas.save();
		canvas.translate(l - w / 2, t - h - 5);
		infoView.draw(canvas);
		canvas.restore();
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public boolean equals(Object o) {
		if(!(o instanceof Layer))
			return false;
		return ((Layer)o).getId()==this.mId;
	}

	public enum Type {
		POINT,
		TASK,
		ROUTE
	}
	
}
